今天的實作有點兒難度,是要用到你的視訊鏡頭,做出一個能夠製造特效、拍照及下載的功能,介面如下:
每拍一張照,下方就會多一張照片,點選即可下載該張照片。
但由於視訊鏡頭牽涉到安全性問題,需要用到https,這邊就不提供實作範例。有興趣的同學可直接下載教材試用。
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
.then(localMediaStream => {
video.srcObject = localMediaStream;
video.play();
})
function paintToCanvas() {
const width = video.videoWidth;
const height = video.videoHeight;
canvas.width = width;
canvas.height = height;
return setInterval(() => {
ctx.drawImage(video, 0, 0, width, height);
}, 16);
}
將視訊鏡頭的解析度同樣設定給畫布,而下方的setInterval()是為了讓畫布能夠和鏡頭同步(若沒設定的話畫布就不會動),根據可負荷效能來調整每多少毫秒要更新畫面一次。function takePhoto() {
// played the sound
snap.currentTime = 0;
snap.play();
// take the data out of the canvas
const data = canvas.toDataURL('image/jpeg');
const link = document.createElement('a');
link.href = data;
link.setAttribute('download', 'handsome');
link.innerHTML = `<img src="${data}" alt="Handsome Man" />`;
strip.insertBefore(link, strip.firsChild);
}
前面snap部分是播放相機快門聲。後面是產生一個下載連結,並以相片的方式呈現。最後insertBefore()是為了將每次新拍的照片都出現在列表最前面。function rgbSplit(pixels) {
for (let i = 0; i < pixels.data.length; i+=4) {
pixels.data[i - 150] = pixels.data[i + 0]; // RED
pixels.data[i + 500] = pixels.data[i + 1]; // GREEN
pixels.data[i - 550] = pixels.data[i + 2]; // Blue
}
return pixels;
}
首先要做特效必須先將畫布的像素抓出來let pixels = ctx.getImageData(0, 0, width, height)
,調整完後再放回去ctx.putImageData(pixels, 0, 0);
。而pixels其實是超大一串由紅、綠、藍、透明度四個數輪流組成的Array(影像每個像素是由RGB組成,每個顏色範圍為0~255,透明度則是0~1)。這個特效的概念很簡單,就只是分別給予紅綠藍不同的差值,例如上面例子就是將迴圈目前像素的紅光值填進前面150個像素位置,把綠光值填近後面第500個像素位置,藍光值填進前面550個像素位置。所以三個顏色就會產生平移的偏差,造成圖片中的效果。